from typing import List, Any

from PyQt5.QtWidgets import QWidget, QGraphicsView, QGraphicsScene, QGraphicsItem
from PyQt5.QtCore import QPoint, QPointF, QRectF, QRect, Qt
from PyQt5.QtGui import QTransform, QPixmap, QPainter, QPen

import Utility.math as UtilMath
import math

from Tools.Transform.Controller.Controller import Controller, ControllerTag
from Tools.Transform.Controller.TransformEvent import TransformEvent
import GUI.Window.Editor as WindowEditor


class Rotater(Controller):
    Name = 'Rotater'
    TagList: List[ControllerTag] = []
    PreviousTransform = None
    RotationOriginalPoint: QPoint = None  # 控制器旋转中心点
    RotationItemOriginalPoint: QPointF = None  # 图元旋转中心点
    CenterTag = None    # 旋转中心Tag

    def __init__(self, parent: QWidget, layer) -> QWidget:
        """
        :param graphicsItem: QGraphicsItem
        :param parent:  QWidget
        :return QWidget #handle of the indicator
        """
        super().__init__(parent, layer)
        self.PreviousTransform = self.graphicsItem.transform()
        self.initTag()
        self.initTagPos()

    def setEditorWidget(self, editorWidget):
        # 编辑组件
        self.editorWidget = editorWidget
        self.editorWidget.confirmAction = self.confirm
        self.editorWidget.cancelAction = self.cancel

    @property
    def __newTag(self):
        return ControllerTag(self.Parent, self)

    def initTag(self):
        # 新建tag
        # 0  1
        #
        # 2  3
        for i in range(0, 4):
            self.TagList.append(self.__newTag)
            self.TagList[i].Index = i
            self.TagList[i].setCursor(Qt.CrossCursor)

    def initTagPos(self):
        tagList = self.TagList
        graphicsItem = self.graphicsItem
        scene: QGraphicsScene = graphicsItem.scene()
        view: QGraphicsView = scene.views()[0]
        if view:
            rect: QRectF = graphicsItem.sceneBoundingRect()
            self.RotationItemOriginalPoint = graphicsItem.mapFromScene(rect.center())
            topLeft = view.mapFromScene(rect.topLeft())
            bottomRight = view.mapFromScene(rect.bottomRight())
            # 视图坐标 → 全局 → ImagePanel坐标
            # center: QPoint = self.Parent.mapFromGlobal(view.mapToGlobal(view.mapFromScene(rect.center())))
            topLeft: QPoint = self.Parent.mapFromGlobal(view.mapToGlobal(topLeft))
            bottomRight: QPoint = self.Parent.mapFromGlobal(view.mapToGlobal(bottomRight))
            rect = QRect(topLeft, bottomRight)
            self.RotationOriginalPoint = rect.center()
            # self.RotationOriginalPoint = center
            # print('topLeft:',topLeft.xRate(), topLeft.yRate())
            # print('bottomRight:', bottomRight.xRate(), bottomRight.yRate())
            for i in range(0, len(tagList)):
                anchor = self._getRectAnchor(rect, i)
                tagList[i].move2(anchor.x(), anchor.y())

            # 绘制中心圆形
            tag = self.__newTag
            tag.move2(self.RotationOriginalPoint.x(), self.RotationOriginalPoint.y())
            tag.show()
            tag.setEnabled(False)
            self.CenterTag = tag

    def updateTagPos(self, degree):
        anchor = self.RotationOriginalPoint
        ax, ay = anchor.x(), anchor.y()
        if degree < 0:
            degree = 360 + degree
        for tag in self.TagList:
            x = (tag.x2 - ax) * math.cos(degree) - (tag.y2 - ay) * math.sin(degree) + ax
            y = (tag.x2 - ax) * math.sin(degree) + (tag.y2 - ay) * math.cos(degree) + ay
            tag.move2(x, y)



    @staticmethod
    def _getRectAnchor(rect: QRectF, anchorIndex):
        """
        0  # 1
        #  # #
        2  # 3
        :param rect: QRectF | QRect
        :param anchorIndex:
        :return:
        """
        if anchorIndex == 0:
            anchor = rect.topLeft()
        elif anchorIndex == 1:
            anchor = rect.topRight()
        elif anchorIndex == 2:
            anchor = rect.bottomLeft()
        elif anchorIndex == 3:
            anchor = rect.bottomRight()
        else:
            anchor = rect.center()
        return anchor

    def onTransformEvent(self, event: TransformEvent):
        """
        缩放器操作
        :param event: TransformEvent
        :return:
        """
        # print('onTransform')
        tag: ControllerTag = self.OperatingTag
        if tag is None:
            return
        graphicsItem = self.graphicsItem
        scene: QGraphicsScene = graphicsItem.scene()
        view: QGraphicsView = scene.views()[0]
        if view:
            previous = event.PreviousMousePos
            current = event.CurrentMousePos
            x1, y1, x2, y2 = previous.x(), previous.y(), current.x(), current.y()   # 坐标使用的是父对象(ControllerPanel)的坐标系
            anchor = self.RotationOriginalPoint # 控制面板的旋转中心
            # 角度(在控制面板上计算)
            degree1 = UtilMath.degreeBetweenTwoPoints(anchor.x(), anchor.y(), x1, y1)
            degree2 = UtilMath.degreeBetweenTwoPoints(anchor.x(), anchor.y(), x2, y2)
            degree = degree2 - degree1
            if degree > 0:
                degree = 10
            else:
                degree = - 10
            # 变换
            anchor = self.RotationItemOriginalPoint
            transform = QTransform()
            transform.translate(anchor.x(), anchor.y())
            transform.rotate(degree)
            graphicsItem.setTransform(transform, True)
            transform.reset()
            transform.translate(- anchor.x(), - anchor.y())
            graphicsItem.setTransform(transform, True)
            self.updateTagPos(degree)

    def destroy(self):
        for each in self.TagList:
            each.deleteLater()
        self.TagList.clear()
        self.CenterTag.deleteLater()
        # 删除控制器编辑面板
        WindowEditor.delEditor(self.editorWidget)
        # 移除控制器
        self.Parent.removeController(self)
        Controller.destroy(self)
        print('旋转器删除')

    def confirm(self):
        print('旋转器确认')
        self.destroy()
        # 保存图层
        self.layer.updateImage()

    def cancel(self):
        print('旋转器取消')
        self.graphicsItem.setTransform(self.PreviousTransform)
        self.destroy()
